package com.artisan.web.action;

import com.artisan.common.utils.wxpay.MD5Util;
import com.artisan.common.utils.wxpay.PayConfig;
import com.artisan.common.utils.wxpay.WxXmlUtil;
import com.artisan.common.utils.wxpay.XMLUtil;
import com.artisan.commonweb.result.ActionResult;
import com.artisan.medium.admin.service.WxRefundService;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by szw on 2017/8/8.
 */
@Controller
@RequestMapping("/admin/")
public class WxRefundController {

	private static final Logger log = LogManager.getLogger(WxRefundController.class);

	@Autowired
	private WxRefundService wxRefundService;

	/**
	 * 调用微信申请退款接口
	 * @param orderNo
	 * @return
	 */
	@ResponseBody
	@RequestMapping("refund")
	public Object refundMoney(String orderNo) {

		ActionResult actionResult = new ActionResult();

		try {
			Map<String, String> result = wxRefundService.refundMoney(orderNo);
			if ("SUCCESS".equals(result.get("code"))) {
				actionResult.setCode(200);
			} else {
				actionResult.setCode(300);
				actionResult.setHint(result.get("msg"));
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("申请微信退款失败." + e.getMessage());
			actionResult.setCode(300);
			actionResult.setHint("申请退款失败");
			return actionResult;
		}

		return actionResult;
	}

	/**
	 * 微信退款结果通知接口
	 * @param request
	 * @param response
	 * @return
	 */
	@ResponseBody
	@RequestMapping("refundResult")
	public Object returnResult(HttpServletRequest request, HttpServletResponse response) {

		log.info("=============================refundResult========================================");
		try {
			InputStream inStream = request.getInputStream();
			ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			outSteam.close();
			inStream.close();
			String resultStr = new String(outSteam.toByteArray(), "utf-8");
			Map<String, String> resultMap = XMLUtil.doXMLParse(resultStr);
			String resultCode = (String) resultMap.get("return_code");
			if ("SUCCESS".equals(resultCode)) {
				String req_info = (String) resultMap.get("req_info");
				//log.info("微信退款回调数据加密数据：" + req_info);
				log.info("===========================req_info========================================");
				log.info(req_info);
				log.info("===========================================================================");
				byte[] reqInfoDecode = Base64.decodeBase64(req_info.getBytes("utf-8"));
				String keyMD5 = MD5Util.MD5(PayConfig.WeixinGZHPayConfig.KEY).toLowerCase();
				String reqInfo = AESDncode(keyMD5, reqInfoDecode);
				log.info("解密后的req_info--xml: =" + reqInfo);
				Map<String, String> reqMap = XMLUtil.doXMLParse(reqInfo);
				if (reqMap != null) {
					String status = reqMap.get("refund_status");
					if ("SUCCESS".equals(status)) {
						String orderNo = reqMap.get("out_trade_no");
						wxRefundService.updateOrderStatusByRefundResult(orderNo);
					}
				}
			} else {
				String msg = (String) resultMap.get("return_msg");
				log.info("Error msg:" + msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("error msg of refundResult:" + e.getMessage());
		}

		Map<String, String> returnMap = new HashMap<>();
		returnMap.put("return_code", "SUCCESS");
		String xml = WxXmlUtil.ArrayToXml(returnMap);
		return xml;
	}

	private static String AESDncode(String encodeRules, byte[] byte_content){
		try {
			//1.构造密钥生成器，指定为AES算法,不区分大小写
			//KeyGenerator keygen = KeyGenerator.getInstance("AES");
			//2.根据ecnodeRules规则初始化密钥生成器
			//生成一个128位的随机源,根据传入的字节数组
			//SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
			//random.setSeed(encodeRules.getBytes("utf-8"));
			//keygen.init(128, random);//new SecureRandom(encodeRules.getBytes()));
			//3.产生原始对称密钥
			//SecretKey original_key = keygen.generateKey();
			//4.获得原始对称密钥的字节数组
			//byte [] raw = original_key.getEncoded();
			//5.根据字节数组生成AES密钥
			//SecretKey key = new SecretKeySpec(raw, "AES");
			SecretKeySpec key = new SecretKeySpec(encodeRules.getBytes(), "AES");
			//6.根据指定算法AES自成密码器
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			//7.初始化密码器，第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作，第二个参数为使用的KEY
			cipher.init(Cipher.DECRYPT_MODE, key);
			//8.将加密并编码后的内容解码成字节数组
			//byte [] byte_content = new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
			byte [] byte_decode=cipher.doFinal(byte_content);
			String AES_decode=new String(byte_decode,"utf-8");
			return AES_decode;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}

		//如果有错就返加null
		return null;
	}

	/*public static void main(String[] args) throws Exception {
		String secretStr = "CFUntTK8EAUsAGSZn2eu11VypLKBPkhWrW6Miy4wSr/2blu+evC0EqmU6++Lij6P+Ja4jT0dfBoyB3umhjU+nbxal4iiAItil2ceqBpxyvu1J+AXY7TGJ3scPdVeBf7/mqv+st6RtIxsXm1bPrju8p+QiXJhcR24ADLUIOdIN3pXssEjggBcev6n6P1lvdoPrqDw1E67ewjJEKTMQjPMEin6bDcKByg+8diw1oILNIja2eq2bHMpJqEEJyV/vi5BbQ4fLWP/qPZgt4v+lH0FUT1FU4KJoBRtKraTseWv2BUAXU6b05MvnYwmmkjl0lDQpL9+fYqFw9UEIrv6UhADradaN8yMhra7k/x5xCxwnbzq1ZPJ7zIqQOvsEyr2oVeq9hqvFLXrNotD1x7/471EOoqacIH/MLelxz4XZ9EEgHn+3r7dcQXYFMcoDtdQ2gbclAI3GnHKvCtOccJMzZSY0xAzPOu9OTEMfGQymbp7nsH0CxUnA0KLlUtGBSJt4utuya9F4Uh0rhCvhPpLBP6W7JDfh5q+rZfW5nvePPqItAy2hrqRG8EbdDLQjma1XQkMpAyyP7vKlgAHtLvaqr2tPxS9JN6Z+ye1uyJpz80X9LD88YWe9BJNrU27La8c4Ftmo9M3YQxA1PIRoHkdxNlkYvy1Y1wWuhzE+v5vX8WimRLSqEuBxNIKByRLp5WgVLMGCnoa5AfZxSBXmdvhFMYARQD4UdZhfyPMUaL0EfWdty6mxAs7ruvJUlJqAknjPGsl5vm1vj3cL2yWA+SJbKMe9iYRan5Gcj1N2ZElrBk6ZHNVJogO+UZ4KXFxTvTf4EPgQ9gby6jc3RJsiOk7lpY07kY6ONBiGeKpDxmboSEYBBUKjujJi5g6UFp9n1JydCbcPUVTgomgFG0qtpOx5a/YFeQc3dhimT7fei93mTfhwLggIy5+6zLFgs95WkcMn7A9EB1lCQ/PssdojSzWuj/XJDrqOk3o1crf3wDkicIIevHOSh7C929OP+WFsPkmRbr5wk+YFMjGQmXVsdsgzSpsV9CfPyJAMQfPo3Lj0arwUeM=";

		//byte[] reqInfoDecode = Base64.decodeBase64(secretStr.getBytes("utf-8"));
		byte[] reqInfoDecode = (new Base64()).decode(secretStr.getBytes("utf-8"));
		String str = new String(reqInfoDecode, "utf-8");
		System.out.println("》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
		System.out.println(str);
		System.out.println("》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
		//byte[] base64Str = new BASE64Decoder().decodeBuffer(secretStr);
		//System.out.println("reqInfoDecode: " + reqInfoDecode);
		String keyMD5 = MD5Util.MD5(PayConfig.WeixinGZHPayConfig.KEY).toLowerCase();
		System.out.println("keyMD5: " + keyMD5);
		String md52 = MD5(PayConfig.WeixinGZHPayConfig.KEY).toLowerCase();
		System.out.println("keyMD52: " + md52);
		//String reqInfoStr = new String(reqInfoDecode, "utf-8");
		//System.out.println("reqInfoStr: " + reqInfoStr);
		//System.out.println("reqInfoStr: " + reqInfoStr.length());
		String reqInfo = AESDncode(keyMD5, reqInfoDecode);

		System.out.println("reqInfoStr: " + reqInfo);
		*//*String content = "test12345";
		String keyMD5 = MD5Util.MD5(PayConfig.WeixinGZHPayConfig.KEY).toLowerCase();
		//加密
		System.out.println("加密前：" + content);
		byte[] encryptResult = encrypt(content, keyMD5);
		//解密
		String decryptResult = AESDncode(keyMD5, encryptResult);
		System.out.println("解密后：" + decryptResult);*//*
	}*/

	/**
	 * 加密
	 *
	 * @param content 需要加密的内容
	 * @param password  加密密码
	 * @return
	 */
	public static byte[] encrypt(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	private static String MD5(String sourceStr) {
		String result = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(sourceStr.getBytes());
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			result = buf.toString();
			//System.out.println("MD5(" + sourceStr + ",32) = " + result);
			//System.out.println("MD5(" + sourceStr + ",16) = " + buf.toString().substring(8, 24));
		} catch (NoSuchAlgorithmException e) {
			System.out.println(e);
		}
		return result;
	}

}
